package vehiculo;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import celda.Celda;
import juego.Direccion;
import juego.Juego;
import mapa.Mapa;
import mapa.Posicion;
import objetoDeMapa.ObjetoDeMapa;

public class Vehiculo {

	private Identidad identidad;
	private int movimientos;
	private Mapa mapa;
	private Posicion posicion;
	private boolean listoParaJugar;
	private Juego juego;
	private boolean puedeAvanzar;
	private int cantidadDeCeldaQueAvanza;

	public void setJuego(Juego juego) {
		this.juego = juego;
	}

	public Juego getJuego() {
		return this.juego;
	}

	public Vehiculo(Identidad identidad) {
		identidad.setVehiculo(this);
		this.identidad = identidad;
		this.movimientos = 0;
		this.listoParaJugar = false;
		this.puedeAvanzar=true;
		cantidadDeCeldaQueAvanza=3;
	}

	public void chocar(ObjetoDeMapa objetoDeMapa) {
		identidad.chocar(objetoDeMapa);
	}

	public Identidad getIdentidad() {
		return this.identidad;
	}

	public void sumarMovimiento(int i) {
		this.movimientos += i;
	}

	public void aplicarSorpresa(int i) {
		this.movimientos = this.movimientos * i / 100;
	}

	public int movimientos() {
		return this.movimientos;
	}

	public void setEstado(Identidad nuevaIdentidad) {
		nuevaIdentidad.setVehiculo(this);
		this.identidad = nuevaIdentidad;
	}

	public static Vehiculo crearConIdentidad(Identidad identidad) {

		return new Vehiculo(identidad);

	}

	public void setPosxy(int x, int y) {
		
		this.posicion = new Posicion(x,y);
		this.listoParaJugar = true;
	}

	public int getPosx() {
		return this.posicion.getPosX();
	}

	public int getPosy() {
		return this.posicion.getPosY();
	}

	public boolean estaListoParaJugar() {
		return this.listoParaJugar;
	}

	public void setMapa(Mapa mapa) {
		this.mapa = mapa;
	}

	public Mapa getMapa() {
		return mapa;
	}
	
	public void noAvanzar(){
		puedeAvanzar = false;
	}
	
	public void moverse() {
		this.sumarMovimiento(1);
	}
	
	public void moverse(Direccion direccion) {
		
		if (this.movimientoValido(direccion)){
			int celdasRecorridas = 0;
			while(puedeAvanzar && (celdasRecorridas<cantidadDeCeldaQueAvanza+1)){				
				Celda celda = this.buscarCeldaEnDireccion(direccion, celdasRecorridas);
				if(!celda.esManzana()){
					if(celda.getObjeto()!= null)
						this.chocar(celda.getObjeto());
				}else{
					puedeAvanzar = false;
				}							
				celdasRecorridas++;
			}			
			if(puedeAvanzar){
				this.avanzarANuevaPosicion(direccion);
				this.moverse();
				}
		}		
		puedeAvanzar = true;		
	}
	
	private boolean movimientoValido(Direccion direccion){
		
		if(direccion == Direccion.Arriba){
			if((posicion.getPosY() - cantidadDeCeldaQueAvanza) < 0)
				return false;
		} else if(direccion == Direccion.Abajo){
			if((posicion.getPosY() + cantidadDeCeldaQueAvanza) > mapa.getDimension()-1)
				return false;
		} else if(direccion == Direccion.Derecha){	
			if((posicion.getPosX() + cantidadDeCeldaQueAvanza) > mapa.getDimension()-1)
				return false;
		} else if(direccion == Direccion.Izquierda ){
			if((posicion.getPosX() - cantidadDeCeldaQueAvanza) < 0)
				return false;
		}
		
		return true;
	}
	
	private Celda buscarCeldaEnDireccion(Direccion direccion,int distanciDeLaCeldas){
		
		int enx=posicion.getPosX(), eny=posicion.getPosY();
		
		if(direccion == Direccion.Arriba)
			eny-= distanciDeLaCeldas;
		else if(direccion == Direccion.Abajo)
			eny+= distanciDeLaCeldas;
		else if(direccion == Direccion.Derecha)	
			enx+= distanciDeLaCeldas;
		else if(direccion == Direccion.Izquierda )
			enx-= distanciDeLaCeldas;
		
		return this.mapa.getCeldaEnPosicion(enx, eny);
		
	}
	
	private void avanzarANuevaPosicion(Direccion direccion){
			if(direccion == Direccion.Arriba)
				posicion.restarEnY(this.cantidadDeCeldaQueAvanza);
			else if(direccion == Direccion.Abajo)
				posicion.sumarEnY(this.cantidadDeCeldaQueAvanza);
			else if(direccion == Direccion.Derecha)	
				posicion.sumarEnX(this.cantidadDeCeldaQueAvanza);
			else if(direccion == Direccion.Izquierda )
				posicion.restarEnX(this.cantidadDeCeldaQueAvanza);
	}

	public void setMovimientos(int movimientos){
		this.movimientos = movimientos;
	}
	
	
	public Element serializar(org.w3c.dom.Document dom) throws ParserConfigurationException{
		
        Element vehiculoSerializado = dom.createElement("Vehiculo");
        
        Element movimientos = dom.createElement("Movimientos");
        movimientos.setTextContent(((Integer)this.movimientos).toString());
        
        Element listoParaJugar = dom.createElement("ListoParaJugar");
        listoParaJugar.setTextContent(this.listoParaJugar? "true" : "false");
        
        Element nodoIdentidad = dom.createElement("Identidad");
        nodoIdentidad.setTextContent(this.identidad.getClass().getName());
		
		vehiculoSerializado.appendChild(nodoIdentidad);
        vehiculoSerializado.appendChild(this.posicion.serializar(dom));
        vehiculoSerializado.appendChild(movimientos);
        vehiculoSerializado.appendChild(listoParaJugar);
        
        
		return vehiculoSerializado ;
		 
	}
	
	public static Vehiculo deserializar(Node vehiculo) {
		
		Vehiculo nuevoVehiculo = Vehiculo.crearConIdentidad(new IdentidadAuto());
		try{
						
			for(int i=0 ; i < vehiculo.getChildNodes().getLength(); i++)
			{
				Node nodo = vehiculo.getChildNodes().item(i);
										
				if(nodo.getNodeName() == "Posicion"){
					nuevoVehiculo.posicion = Posicion.deserializar(nodo);
				}else
				
				if(nodo.getNodeName() == "Identidad"){
					Object identidadVehiculo = null;
					try {
						identidadVehiculo = Class.forName(nodo.getTextContent()).newInstance();
					} catch (InstantiationException e) {
						e.printStackTrace();
					}
					
					nuevoVehiculo.setEstado((Identidad) identidadVehiculo);
				}
				
				if(nodo.getNodeName() == "ListoParaJugar"){
					nuevoVehiculo.listoParaJugar = nodo.getTextContent().equals("true");
				}else
				
				if(nodo.getNodeName() == "Movimientos"){
					nuevoVehiculo.movimientos = Integer.parseInt(nodo.getTextContent());
				}

			}
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
		}
		
		return nuevoVehiculo;
	}
	
}

